package com.xm.settlement.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 *  redis缓存工具类
 *  @author
 */
@Service
public class RedisCacheUtil<T> {

    @Autowired  public RedisTemplate redisTemplate;


    /**
     * 缓存基本的对象，Integer、String、实体类等
     * @param key 缓存的键值
     * @param value 缓存的值
     * @return  缓存的对象
     */
    public <T> ValueOperations<String,T> setCacheObject(String key, T value)
    {
        ValueOperations<String,T> operation = redisTemplate.opsForValue();
        operation.set(key,value);
        return operation;
    }

    /**
     * 获得缓存的基本对象。
     * @param key  缓存键值
     * @param
     * @return   缓存键值对应的数据
     */
    public <T> T getCacheObject(String key/*,ValueOperations<String,T> operation*/)
    {
        try{
            ValueOperations<String,T> operation = redisTemplate.opsForValue();
            return operation.get(key);
        }catch (SerializationException e){
            //e.printStackTrace();
            System.out.println(""+e.getMessage());
            return null;
        }
    }

    /**
     * 缓存List数据
     * @param key  缓存的键值
     * @param dataList 待缓存的List数据
     * @return   缓存的对象
     */
    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList)
    {
        ListOperations listOperation = redisTemplate.opsForList();
        if(null != dataList)
        {
            int size = dataList.size();
            for(int i = 0; i < size ; i ++)
            {
                listOperation.rightPush(key,dataList.get(i));
            }
        }
        return listOperation;
    }

    /**
     * 获得缓存的list对象
     * @param key 缓存的键值
     * @return  缓存键值对应的数据
     */
    public <T> List<T> getCacheList(String key)
    {
        List<T> dataList = new ArrayList<T>();
        ListOperations<String,T> listOperation = redisTemplate.opsForList();
        Long size = listOperation.size(key);
        for(int i = 0 ; i < size ; i ++)
        {
            dataList.add((T) listOperation.leftPop(key));
        }

        return dataList;
    }

    /**
     * 缓存Set
     * @param key  缓存键值
     * @param dataSet 缓存的数据
     * @return   缓存数据的对象
     */
    public <T> BoundSetOperations<String,T> setCacheSet(String key, Set<T> dataSet)
    {
        BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key);
  /*T[] t = (T[]) dataSet.toArray();
    setOperation.add(t);*/

        Iterator<T> it = dataSet.iterator();
        while(it.hasNext())
        {
            setOperation.add(it.next());
        }

        return setOperation;
    }

    /**
     * 获得缓存的set
     * @param key
     * @param operation
     * @return
     */
    public Set<T> getCacheSet(String key/*,BoundSetOperations<String,T> operation*/)
    {
        Set<T> dataSet = new HashSet<T>();
        BoundSetOperations<String,T> operation = redisTemplate.boundSetOps(key);

        Long size = operation.size();
        for(int i = 0 ; i < size ; i++)
        {
            dataSet.add(operation.pop());
        }
        return dataSet;
    }

    /**
     * 缓存Map
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String,String,T> setCacheMap(String key, Map<String,T> dataMap)
    {

        HashOperations hashOperations = redisTemplate.opsForHash();
        if(null != dataMap)
        {

            for (Map.Entry<String, T> entry : dataMap.entrySet()) {

    /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */
                hashOperations.put(key,entry.getKey(),entry.getValue());
            }

        }

        return hashOperations;
    }

    /**
     * 获得缓存的Map
     * @param key
     * @param hashOperation
     * @return
     */
    public <T> Map<String,T> getCacheMap(String key/*,HashOperations<String,String,T> hashOperation*/)
    {
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        /*Map<String, T> map = hashOperation.entries(key);*/
        return map;
    }


    /**
     * 缓存Map
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String,Integer,T> setCacheIntegerMap(String key,Map<Integer,T> dataMap)
    {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if(null != dataMap)
        {
            for (Map.Entry<Integer, T> entry : dataMap.entrySet()) {
                /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */
                hashOperations.put(key,entry.getKey(),entry.getValue());
            }
        }
        return hashOperations;
    }

    /**
     * 获得缓存的Map
     * @param key
     * @param hashOperation
     * @return
     */
    public <T> Map<Integer,T> getCacheIntegerMap(String key/*,HashOperations<String,String,T> hashOperation*/)
    {
        Map<Integer, T> map = redisTemplate.opsForHash().entries(key);
        /*Map<String, T> map = hashOperation.entries(key);*/
        return map;
    }

    /**
     * 设置存储时间的Map
     * 默认 10分钟
     * */
    public boolean setKeyTime(String key ,Long msg ,Long time){
        if( time == null || time <= 0){
            redisTemplate.opsForValue().set(key, msg);
            redisTemplate.expire(key,2 , TimeUnit.MINUTES);
        }else{
            redisTemplate.opsForValue().set(key, msg);
            redisTemplate.expire(key,time , TimeUnit.MINUTES);
        }
        return  true;
    }

    /**
     * 判断key是否过期
     * */
    public String  getKeyTime(String key ){
        if(redisTemplate.hasKey(key)){
            return   ((Long) redisTemplate.opsForValue().get(key) ).toString() ;
        }
        return  null;
    }


    /**
     * 删除key
     * */
    public Long del(final String... keys) {
        return (Long) redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                long result = 0;
                for (int i = 0; i < keys.length; i++) {
                    result = connection.del(keys[i].getBytes());
                }
                return result;
            }
        });
    }

    /**
     * 删除key
     * */
    public Long delOne(final String keys) {
        return (Long) redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                long result =  connection.del(keys.getBytes());
                return result;
            }
        });
    }

}
